package group

import (
	"fmt"
	"time"
)

// Conn 调度函数
type Conn interface {
	Time() int64        // 占用开始时间
	Value() interface{} // 传递值
}

// Group 调度
type Group interface {
	Init(size int)                                 // 创建
	Close()                                        // 关闭
	Go(fn func(conn Conn), value interface{}) bool // 调度
	ForEach(fn func(conn Conn))                    // 历遍
}

// 调度对象
type conn struct {
	t     int64
	id    int
	fn    func(conn Conn)
	value interface{}
	run   chan struct{}
	group *group
}

func (conn *conn) init() {
	conn.group.gid <- conn.id
	for range conn.run {
		// 执行调度
		func() {
			// 开始调度
			conn.fn(conn)
		}()
		// 执行结束放回
		conn.t = -1
		// 放回
		conn.group.gid <- conn.id
	}
}
func (conn *conn) close() {
	conn.group = nil
	close(conn.run)
}
func (conn *conn) Time() int64 {
	return conn.t
}
func (conn *conn) Value() interface{} {
	return conn.value
}

// group 调度实现
type group struct {
	g       []*conn
	gid     chan int
	isClose bool
}

func (g *group) Init(size int) {
	g.g = make([]*conn, size)    // 创建调度对象
	g.gid = make(chan int, size) // 最大调度对象
	// 启动携程
	fmt.Println(size)
	for i := 0; i < size; i++ {
		g.g[i] = &conn{
			id:    i,
			group: g,
			run:   make(chan struct{}),
		}

		go g.g[i].init()
	}
}
func (g *group) Go(fn func(conn Conn), value interface{}) bool {
	// 通过 Gid 得到 G
	if id, ok := <-g.gid; ok {
		conn := g.g[id]
		conn.t = Ts()
		conn.fn = fn
		conn.value = value
		conn.run <- struct{}{}
		return true
	}
	return false
}
func (g *group) Close() {
	for i, n := 0, len(g.g); i < n; i++ {
		// 关闭调度
		g.g[<-g.gid].close()
	}
	close(g.gid)
}
func (g *group) ForEach(fn func(conn Conn)) {
	for i, n := 0, len(g.g); i < n; i++ {
		if g.g[i].t != -1 {
			fn(g.g[i])
		}
	}
}

// NewGroup 创建调度池
func NewGroup() Group {
	return &group{}
}

// CloseGroup 等待关闭
func CloseGroup(group Group) {
	for {
		i := 0
		group.ForEach(func(conn Conn) { i++ })
		if i == 0 {
			group.Close()
			return
		}
		<-time.After(time.Second)
	}
}
